{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Serpy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you're just looking for deserialization, then `Serpy` might work for you. It is extremely fast, but only provides serialization.\n",
    "\n",
    "You can read more about Serpy here: https://serpy.readthedocs.io/en/latest/\n",
    "\n",
    "Here's a simple example first, using our goto Person object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Person:\n",
    "    def __init__(self, name, age):\n",
    "        self.name = name\n",
    "        self.age = age\n",
    "        \n",
    "    def __repr__(self):\n",
    "        return f'Person(name={self.name}, age={self.age})'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import serpy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Very similarly to `Marshmallow` we need to define a schema for the serialization - Serpy calls those objects serializers:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PersonSerializer(serpy.Serializer):\n",
    "    name = serpy.StrField()\n",
    "    age = serpy.IntField()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "p1 = Person('Michael Palin', 75)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'Michael Palin', 'age': 75}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "PersonSerializer(p1).data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, we can get more complex schemas defined.\n",
    "\n",
    "Let's implement a schema for our `Movie` example we did in a previous video on Marshmallow."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Movie:\n",
    "    def __init__(self, title, year, actors):\n",
    "        self.title = title\n",
    "        self.year = year\n",
    "        self.actors = actors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MovieSerializer(serpy.Serializer):\n",
    "    title = serpy.StrField()\n",
    "    year = serpy.IntField()\n",
    "    actors = PersonSerializer(many=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "p2 = Person('John Cleese', 79)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "movie = Movie('Parrot Sketch', 1989, [p1, p2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('Parrot Sketch',\n",
       " 1989,\n",
       " [Person(name=Michael Palin, age=75), Person(name=John Cleese, age=79)])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "movie.title, movie.year, movie.actors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'title': 'Parrot Sketch',\n",
       " 'year': 1989,\n",
       " 'actors': [{'name': 'Michael Palin', 'age': 75},\n",
       "  {'name': 'John Cleese', 'age': 79}]}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "MovieSerializer(movie).data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the result of serialization is to a basic Python dictionary, and you can takes this further to JSON or YAML using the standard library `json` module or `PyYaml`.\n",
    "\n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "import json\n",
    "import yaml"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'{\"title\": \"Parrot Sketch\", \"year\": 1989, \"actors\": [{\"name\": \"Michael Palin\", \"age\": 75}, {\"name\": \"John Cleese\", \"age\": 79}]}'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "json.dumps(MovieSerializer(movie).data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "actors:\n",
      "- age: 75\n",
      "  name: Michael Palin\n",
      "- age: 79\n",
      "  name: John Cleese\n",
      "title: Parrot Sketch\n",
      "year: 1989\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(yaml.dump(MovieSerializer(movie).data, \n",
    "          default_flow_style=False))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
